﻿using System;
using System.Text;
using System.Collections.Generic;
using System.IO;

namespace ServerFramework.Net.Msg
{
    public class MsgPacket
    {
        public int lenth;            //包长
        public int msgId;            //消息id
        public int userId;           //用户id
        public int status;          //预留字段
        public byte[] data;          //数据部分
        public object userToken;    //用户网络数据

        public MsgPacket()
        { }

        public MsgPacket(int msgId,int userId,int fillData,byte [] data)
        {
            this.msgId = msgId;
            this.userId = userId;
            this.status = fillData;
            this.data = data;
            lenth = 0;
            userToken = null;
        }

        public T GetToken<T>()
        {
            return (T)userToken;
        }

        /// <summary>
        /// 转换成消息包 可进行中转发送
        /// </summary>
        /// <returns></returns>
        public byte[] ToPacket()
        {
            using (MemoryStream stream = new MemoryStream())
            {
                BinaryWriter writer = new BinaryWriter(stream);
                writer.Write(lenth);
                writer.Write(msgId);
                writer.Write(userId);
                writer.Write(status);
                writer.Write(data);
                writer.Close();
                return stream.ToArray();
            }
        }

        public override string ToString()
        {
            string dataString = Encoding.UTF8.GetString(data);
            return string.Format("len={0},msgId={1},userId={2},status={3},data={4}", lenth, msgId, userId, status, dataString);
        }

        public static T PacketToObj<T>(MsgPacket msg) where T : MsgBase,new()
        {
            T t = null;
            if (typeof(T).BaseType == typeof(BinaryMsg))
            {
                t = BinaryMsg.Unpack<T>(msg);
            }
            else
            {
                t = new T();
                t.Unpack(msg);
            }
            return t;
        }

        /// <summary>
        /// 进行粘包处理
        /// </summary>
        /// <param name="cache"></param>
        /// <returns></returns>
        public static byte[] SplitPacket(ref List<byte> cache)
        {
            if (cache.Count < 4) return null;
            byte[] cacheBuffer = cache.ToArray();
            int length = BitConverter.ToInt32(cacheBuffer,0);//从缓存中读取int型消息体长度
            //如果消息体长度 大于缓存中数据长度 说明消息没有读取完 等待下次消息到达后再次处理
            if (length > cacheBuffer.Length)
            {
                return null;
            }
            //读取正确长度的数据
            byte[] result = new byte[length];
            Buffer.BlockCopy(cacheBuffer, 0, result, 0, length);
            //将读取的数据删除
            cache.RemoveRange(0, length);
            return result;
        }

        /// <summary>
        /// 拆包
        /// </summary>
        /// <returns></returns>
        public static MsgPacket SplitPacket(object userToken,byte [] buffer,int offset,int length)
        {
            MsgPacket packet = new MsgPacket();
            MemoryStream stream = new MemoryStream(buffer,offset,length);
            BinaryReader reader = new BinaryReader(stream);
            packet.lenth = reader.ReadInt32();
            packet.msgId = reader.ReadInt32();
            packet.userId = reader.ReadInt32(); ;
            packet.status = reader.ReadInt32();
            packet.userToken = userToken;
            packet.data = new byte[length - MsgBase.MSG_HEAD_LENTH];
            Buffer.BlockCopy(buffer, offset + MsgBase.MSG_HEAD_LENTH, packet.data, 0, packet.data.Length);
            stream.Close();
            reader.Close();
            return packet;
        }

     
    }
}
